home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / util / misc / MUser17src.lha / MultiUser / src / Library / Task.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-07  |  17.8 KB  |  800 lines

  1. /************************************************************
  2. * MultiUser - MultiUser Task/File Support System                *
  3. * ---------------------------------------------------------    *
  4. * Task Management Routines                                                *
  5. * ---------------------------------------------------------    *
  6. * © Copyright 1993-1994 Geert Uytterhoeven                        *
  7. * All Rights Reserved.                                                    *
  8. ************************************************************/
  9.  
  10.  
  11. #include <exec/execbase.h>
  12. #include <exec/alerts.h>
  13. #include <intuition/intuitionbase.h>
  14. #include <proto/exec.h>
  15. #include <proto/dos.h>
  16. #include <proto/intuition.h>
  17.  
  18. #include "Memory.h"
  19. #include "Task.h"
  20. #include "Config.h"
  21. #include "Misc.h"
  22. #include "LibHeader.h"
  23. #include "Monitor.h"
  24. #include "UserInfo.h"
  25.  
  26.  
  27.     /*
  28.      *        Static Routines
  29.      */
  30.  
  31. static struct muTaskLevel *AllocTaskLevel(struct muExtOwner *owner);
  32. static void FreeTaskLevel(struct muTaskLevel *level);
  33. static struct muTaskNode *AllocTaskNode(struct Task *task, ULONG defprotection);
  34. static void FreeTaskNode(struct muTaskNode *node);
  35. static struct muTaskNode *FindTaskNode(struct Task *task);
  36. static void AddTaskLevel(struct muTaskLevel *level, struct muTaskLevel *dest);
  37. static void RemTaskLevel(struct muTaskLevel *level);
  38. static void MoveTaskLevel(struct muTaskLevel *level, struct muTaskLevel *dest);
  39. static void MoveAll(struct muTaskLevel *source, struct muTaskLevel *dest);
  40. static void AddTaskNode(struct muTaskNode *node, struct muTaskLevel *dest);
  41. static void RemTaskNode(struct muTaskNode *node);
  42. static void MoveTaskNode(struct muTaskNode *node, struct muTaskLevel *dest);
  43. static void CleanUpTaskLevel(struct muTaskLevel *level);
  44. static void __saveds CleanUpBody(void);
  45.  
  46.  
  47.     /*
  48.      *        Extended Owner Information Structure for root
  49.      */
  50.  
  51. struct muExtOwner RootExtOwner = {
  52.     muROOT_UID, muROOT_GID, 0
  53. };
  54.  
  55.  
  56.     /*
  57.      *        Allocate a Task Level
  58.      */
  59.  
  60. static struct muTaskLevel *AllocTaskLevel(struct muExtOwner *owner)
  61. {
  62.     struct muTaskLevel *level;
  63.     ULONG size;
  64.  
  65.     size = sizeof(struct muTaskLevel);
  66.     if (owner)
  67.         size += owner->NumSecGroups*sizeof(UWORD);
  68.     if (level = MAlloc(size)) {
  69.         NewList((struct List *)&level->Tasks);
  70.         NewList((struct List *)&level->Children);
  71.         if (owner)
  72.             CopyMem(owner, &level->Owner, size-sizeof(struct muTaskLevel)+sizeof(struct muExtOwner));
  73.     }
  74.     return(level);
  75. }
  76.  
  77.  
  78.     /*
  79.      *        Deallocate a Task Level
  80.      */
  81.  
  82. static void __inline FreeTaskLevel(struct muTaskLevel *level)
  83. {
  84.     Free(level, sizeof(struct muTaskLevel)+level->Owner.NumSecGroups*sizeof(UWORD));
  85. }
  86.  
  87.  
  88.     /*
  89.      *        Allocate a Task Node
  90.      *
  91.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  92.      */
  93.  
  94. static struct muTaskNode *AllocTaskNode(struct Task *task, ULONG defprotection)
  95. {
  96.     struct muTaskNode *node;
  97.  
  98.     if (node = MAlloc(sizeof(struct muTaskNode))) {
  99.         node->Task = task;
  100.         node->DefProtection = defprotection;
  101.     }
  102.     return(node);
  103. }
  104.  
  105.  
  106.     /*
  107.      *        Deallocate a Task Node
  108.      *
  109.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  110.      */
  111.  
  112. static void __inline FreeTaskNode(struct muTaskNode *node)
  113. {
  114.     Free(node, sizeof(struct muTaskNode));
  115. }
  116.  
  117.  
  118.     /*
  119.      *        Find the Task Node for a given Task
  120.      *
  121.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  122.      */
  123.  
  124. static struct muTaskNode *FindTaskNode(struct Task *task)
  125. {
  126.     struct MinNode *node;
  127.     struct muTaskNode *tnode;
  128.  
  129.     for (node = muBase->TaskOwnerList[(ULONG)task%TASKHASHVALUE].mlh_Head;
  130.           (node->mln_Succ &&
  131.             ((tnode = (struct muTaskNode *)((ULONG)node-
  132.                          (ULONG)&((struct muTaskNode *)NULL)->ListNode))->Task != task));
  133.           node = node->mln_Succ);
  134.     return(node->mln_Succ ? tnode : NULL);
  135. }
  136.  
  137.  
  138.     /*
  139.      *        Add a Task Level
  140.      *
  141.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  142.      */
  143.  
  144. static void AddTaskLevel(struct muTaskLevel *level, struct muTaskLevel *dest)
  145. {
  146.     AddHead((struct List *)&dest->Children, (struct Node *)&level->Node);
  147.     level->Parent = dest;
  148. }
  149.  
  150.  
  151.     /*
  152.      *        Remove a Task Level
  153.      *
  154.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  155.      */
  156.  
  157. static void __inline RemTaskLevel(struct muTaskLevel *level)
  158. {
  159.     Remove((struct Node *)&level->Node);
  160. }
  161.  
  162.  
  163.     /*
  164.      *        Move a Task Level to another Task Level
  165.      */
  166.  
  167. static void MoveTaskLevel(struct muTaskLevel *level, struct muTaskLevel *dest)
  168. {
  169.     Remove((struct Node *)&level->Node);
  170.     AddHead((struct List *)&dest->Children, (struct Node *)&level->Node);
  171.     level->Parent = dest;
  172. }
  173.  
  174.  
  175.     /*
  176.      *        Move all TaskNodes and TaskLevels to another Task Level
  177.      */
  178.  
  179. static void MoveAll(struct muTaskLevel *source, struct muTaskLevel *dest)
  180. {
  181.     struct muTaskNode *node;
  182.     struct muTaskLevel *level;
  183.  
  184.     while ((node = (struct muTaskNode *)source->Tasks.mlh_Head) && node->LevelNode.mln_Succ)
  185.         MoveTaskNode(node, dest);
  186.     while ((level = (struct muTaskLevel *)source->Children.mlh_Head) && level->Node.mln_Succ)
  187.         MoveTaskLevel(level, dest);
  188. }
  189.  
  190.  
  191.     /*
  192.      *        Add a Task Node to a Task Level
  193.      *
  194.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  195.      */
  196.  
  197. static void AddTaskNode(struct muTaskNode *node, struct muTaskLevel *dest)
  198. {
  199.     AddHead((struct List *)&dest->Tasks, (struct Node *)&node->LevelNode);
  200.     AddHead((struct List *)&muBase->TaskOwnerList[(ULONG)node->Task%TASKHASHVALUE],
  201.               (struct Node *)&node->ListNode);
  202.     node->Level = dest;
  203.     CallMonitors(muTrgB_OwnerChange, muNOBODY_UID, dest->Owner.uid, NULL);
  204. }
  205.  
  206.  
  207.     /*
  208.      *        Remove a Task Node from a Task Level
  209.      *
  210.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  211.      */
  212.  
  213. static void __inline RemTaskNode(struct muTaskNode *node)
  214. {
  215.     Remove((struct Node *)&node->LevelNode);
  216.     Remove((struct Node *)&node->ListNode);
  217.     CallMonitors(muTrgB_OwnerChange, node->Level->Owner.uid, muNOBODY_UID, NULL);
  218. }
  219.  
  220.  
  221.     /*
  222.      *        Move a Task Node to another TaskLevel
  223.      *
  224.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  225.      */
  226.  
  227. static void MoveTaskNode(struct muTaskNode *node, struct muTaskLevel *dest)
  228. {
  229.     Remove((struct Node *)&node->LevelNode);
  230.     AddHead((struct List *)&dest->Tasks, (struct Node *)&node->LevelNode);
  231.     node->Level = dest;
  232.     CallMonitors(muTrgB_OwnerChange, node->Level->Owner.uid, dest->Owner.uid, NULL);
  233. }
  234.  
  235.  
  236.     /*
  237.      *        Clean Up a Task Level
  238.      *
  239.      *        Make sure you have access to the list (via ObtainSemaphore(Shared))!!
  240.      */
  241.  
  242. static void CleanUpTaskLevel(struct muTaskLevel *level)
  243. {
  244.     struct muTaskLevel *parent;
  245.  
  246.     while (level && IsListEmpty((struct List *)&level->Tasks) &&
  247.              IsListEmpty((struct List *)&level->Children)) {
  248.         if (parent = level->Parent)
  249.             RemTaskLevel(level);
  250.         FreeTaskLevel(level);
  251.         level = parent;
  252.     };
  253. }
  254.  
  255.  
  256.     /*
  257.      *        Init Task List
  258.      */
  259.  
  260. void InitTaskList(void)
  261. {
  262.     ULONG i;
  263.  
  264.     ObtainSemaphore(&muBase->TaskOwnerSem);
  265.     for (i = 0; i < TASKHASHVALUE; i++)
  266.         NewList((struct List *)&muBase->TaskOwnerList[i]);
  267.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  268. }
  269.  
  270.  
  271.     /*
  272.      *        Create an Orphan Task Node
  273.      */
  274.  
  275. struct muTaskNode *CreateOrphanTask(struct Task *task, ULONG defprotection)
  276. {
  277.     struct muTaskLevel *level;
  278.     struct muTaskNode *node;
  279.  
  280.     ObtainSemaphore(&muBase->TaskOwnerSem);
  281.     if (level = AllocTaskLevel(NULL))
  282.         if (node = AllocTaskNode(task, defprotection))
  283.             AddTaskNode(node, level);
  284.         else
  285.             FreeTaskLevel(level);
  286.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  287.     return(node);
  288. }
  289.  
  290.  
  291.     /*
  292.      *        Remove all Task Nodes
  293.      */
  294.  
  295. void RemAllTaskNodes(void)
  296. {
  297.     struct muTaskNode *node;
  298.     struct muTaskLevel *level;
  299.     ULONG i;
  300.  
  301.     ObtainSemaphore(&muBase->TaskOwnerSem);
  302.     for (i = 0; i < TASKHASHVALUE; i++)
  303.         while ((node = (struct muTaskNode *)muBase->TaskOwnerList[i].mlh_Head) && node->ListNode.mln_Succ) {
  304.             level = node->Level;
  305.             RemTaskNode(node);
  306.             FreeTaskNode(node);
  307.             CleanUpTaskLevel(level);
  308.         }
  309.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  310. }
  311.  
  312.  
  313.     /*
  314.      *        Push a Task to a new Owner
  315.      */
  316.  
  317. BOOL PushTask(struct Task *task, struct muExtOwner *owner)
  318. {
  319.     BOOL res = FALSE;
  320.     struct muTaskNode *node;
  321.     struct muTaskLevel *child, *parent;
  322.  
  323.     ObtainSemaphore(&muBase->TaskOwnerSem);
  324.     if ((node = FindTaskNode(task)) || (node = CreateOrphanTask(task, DEFPROTECTION))) {
  325.         parent = node->Level;
  326.         if (child = AllocTaskLevel(owner)) {
  327.             MoveTaskNode(node, child);
  328.             AddTaskLevel(child, parent);
  329.             res = TRUE;
  330.         }
  331.     }
  332.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  333.     return(res);
  334. }
  335.  
  336.  
  337.     /*
  338.      *        Push a Task Level to a new Owner
  339.      */
  340.  
  341. BOOL PushTaskLevel(struct Task *task, struct muExtOwner *owner)
  342. {
  343.     BOOL res = FALSE;
  344.     struct muTaskNode *node;
  345.     struct muTaskLevel *child, *parent;
  346.  
  347.     ObtainSemaphore(&muBase->TaskOwnerSem);
  348.     if ((node = FindTaskNode(task)) || (node = CreateOrphanTask(task, DEFPROTECTION))) {
  349.         parent = node->Level;
  350.         if (child = AllocTaskLevel(owner)) {
  351.             MoveAll(parent, child);
  352.             AddTaskLevel(child, parent);
  353.             res = TRUE;
  354.         }
  355.     }
  356.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  357.     return(res);
  358. }
  359.  
  360.  
  361.     /*
  362.      *        Pop a Task to the previous Owner
  363.      */
  364.  
  365. BOOL PopTask(struct Task *task)
  366. {
  367.     BOOL res = FALSE;
  368.     struct muTaskNode *node;
  369.     struct muTaskLevel *child, *parent;
  370.  
  371.     ObtainSemaphore(&muBase->TaskOwnerSem);
  372.     if (node = FindTaskNode(task)) {
  373.         child = node->Level;
  374.         if (parent = child->Parent) {
  375.             MoveTaskNode(node, parent);
  376.             CleanUpTaskLevel(child);
  377.             if (parent->Parent)
  378.                 res = TRUE;
  379.         }
  380.     } else
  381.         CreateOrphanTask(task, DEFPROTECTION);
  382.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  383.     return(res);
  384. }
  385.  
  386.  
  387.     /*
  388.      *        Pop a Task to the previous Owner and Detach when the Root of the Tree is reached
  389.      */
  390.  
  391. BOOL PopTaskDetach(struct Task *task)
  392. {
  393.     BOOL res = FALSE;
  394.     struct muTaskNode *node;
  395.     struct muTaskLevel *child, *parent;
  396.  
  397.     ObtainSemaphore(&muBase->TaskOwnerSem);
  398.     if (node = FindTaskNode(task)) {
  399.         child = node->Level;
  400.         if ((parent = child->Parent) && parent->Parent) {
  401.             MoveTaskNode(node, parent);
  402.             CleanUpTaskLevel(child);
  403.             res = TRUE;
  404.         } else if (parent = AllocTaskLevel(NULL)) {
  405.             MoveTaskNode(node, parent);
  406.             CleanUpTaskLevel(child);
  407.         }
  408.     } else
  409.         CreateOrphanTask(task, DEFPROTECTION);
  410.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  411.     return(res);
  412. }
  413.  
  414.  
  415.     /*
  416.      *        Pop a Task Level to the previous Owner and Detach when the Root of the Tree is reached
  417.      */
  418.  
  419. BOOL PopTaskLevelDetach(struct Task *task)
  420. {
  421.     BOOL res = FALSE;
  422.     struct muTaskNode *node;
  423.     struct muTaskLevel *child, *parent;
  424.  
  425.     ObtainSemaphore(&muBase->TaskOwnerSem);
  426.     if (node = FindTaskNode(task)) {
  427.         child = node->Level;
  428.         if ((parent = child->Parent) && parent->Parent) {
  429.             MoveAll(child, parent);
  430.             CleanUpTaskLevel(child);
  431.             res = TRUE;
  432.         } else if (parent = AllocTaskLevel(NULL)) {
  433.             MoveAll(child, parent);
  434.             CleanUpTaskLevel(child);
  435.         }
  436.     } else
  437.         CreateOrphanTask(task, DEFPROTECTION);
  438.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  439.     return(res);
  440. }
  441.  
  442.  
  443.     /*
  444.      *        Get the Owner (uid:gid) of a Task
  445.      */
  446.  
  447. ULONG GetTaskOwner(struct Task *task)
  448. {
  449.     ULONG owner = muOWNER_NOBODY;
  450.     struct muTaskNode *node;
  451.  
  452.     if (!muBase->SecurityViolation) {
  453.         ObtainSemaphoreShared(&muBase->TaskOwnerSem);
  454.         if (node = FindTaskNode(task))
  455.             owner = muExtOwner2ULONG(&node->Level->Owner);
  456.         ReleaseSemaphore(&muBase->TaskOwnerSem);
  457.     }
  458.     return(owner);
  459. }
  460.  
  461.  
  462.     /*
  463.      *        Get the Owner (struct muExtOwner *) of a Task
  464.      */
  465.  
  466. struct muExtOwner *GetTaskExtOwner(struct Task *task)
  467. {
  468.     struct muExtOwner *owner = NULL;
  469.     struct muTaskNode *node;
  470.     ULONG size;
  471.  
  472.     if (!muBase->SecurityViolation) {
  473.         ObtainSemaphoreShared(&muBase->TaskOwnerSem);
  474.         if (node = FindTaskNode(task)) {
  475.             size = sizeof(struct muExtOwner)+node->Level->Owner.NumSecGroups*sizeof(UWORD);
  476.             if (owner = (struct muExtOwner *)MAlloc(size))
  477.                 CopyMem(&node->Level->Owner, owner, size);
  478.         }
  479.         ReleaseSemaphore(&muBase->TaskOwnerSem);
  480.     }
  481.     return(owner);
  482. }
  483.  
  484.  
  485.     /*
  486.      *        Get the Default Protection Bits for a Task
  487.      */
  488.  
  489. ULONG GetTaskDefProtect(struct Task *task)
  490. {
  491.     ULONG defprotection = DEFPROTECTION;
  492.     struct muTaskNode *node;
  493.  
  494.     ObtainSemaphoreShared(&muBase->TaskOwnerSem);
  495.     if (node = FindTaskNode(task))
  496.         defprotection = node->DefProtection;
  497.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  498.     return(defprotection);
  499. }
  500.  
  501.  
  502.     /*
  503.      *        Set the Default Protection Bits for a Task
  504.      */
  505.  
  506. BOOL SetTaskDefProtect(struct Task *task, ULONG defprotection)
  507. {
  508.     BOOL result;
  509.     struct muTaskNode *node;
  510.  
  511.     ObtainSemaphore(&muBase->TaskOwnerSem);
  512.     if (node = FindTaskNode(task)) {
  513.         node->DefProtection = defprotection;
  514.         result = TRUE;
  515.     } else
  516.         result = (BOOL)CreateOrphanTask(task, defprotection);
  517.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  518.     return(result);
  519. }
  520.  
  521.  
  522.     /*
  523.      *        Set the Default Protection Bits for a Level
  524.      */
  525.  
  526. BOOL SetLevelDefProtect(struct Task *task, ULONG defprotection)
  527. {
  528.     BOOL result;
  529.     struct muTaskLevel *level;
  530.     struct muTaskNode *node;
  531.  
  532.     ObtainSemaphore(&muBase->TaskOwnerSem);
  533.     if (node = FindTaskNode(task)) {
  534.         level = node->Level;
  535.         for (node = (struct muTaskNode *)level->Tasks.mlh_Head; node->LevelNode.mln_Succ;
  536.               node = (struct muTaskNode *)node->LevelNode.mln_Succ)
  537.             node->DefProtection = defprotection;
  538.         result = TRUE;
  539.     } else
  540.         result = (BOOL)CreateOrphanTask(task, defprotection);
  541.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  542.     return(result);
  543. }
  544.  
  545.  
  546.     /*
  547.      *        Replacement for the exec.library AddTask() function
  548.      */
  549.  
  550. APTR __asm __saveds NEWAddTask(register __a1 struct Task *task, register __a2 APTR initpc,
  551.                                          register __a3 APTR finalpc, register __a6 struct ExecBase *sysbase)
  552. {
  553.     struct muTaskNode *node;
  554.     struct muTaskLevel *level;
  555.  
  556.     ObtainSemaphore(&muBase->TaskOwnerSem);
  557.     if (node = FindTaskNode(sysbase->ThisTask)) {
  558.         level = node->Level;
  559.         if (node = AllocTaskNode(task, node->DefProtection))
  560.             AddTaskNode(node, level);
  561.     } else
  562.         CreateOrphanTask(task, DEFPROTECTION);
  563.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  564.     return(muBase->OLDAddTask(task, initpc, finalpc, sysbase));
  565. }
  566.  
  567.  
  568.     /*
  569.      *        Replacement for the exec.library RemTask() function
  570.      */
  571.  
  572. void __asm __saveds NEWRemTask(register __a1 struct Task *task, register __a6 struct ExecBase *sysbase)
  573. {
  574.     struct muTaskNode *node;
  575.     struct muTaskLevel *level;
  576.  
  577.     if (!task)
  578.         task = sysbase->ThisTask;
  579.     ObtainSemaphore(&muBase->TaskOwnerSem);
  580.     if (node = FindTaskNode(task)) {
  581.         level = node->Level;
  582.         RemTaskNode(node);
  583.         FreeTaskNode(node);
  584.         CleanUpTaskLevel(level);
  585.     }
  586.     ReleaseSemaphore(&muBase->TaskOwnerSem);
  587.     muBase->OLDRemTask(task, sysbase);
  588. }
  589.  
  590.  
  591.     /*
  592.      *        Get the Owner (uid:gid) of a Task
  593.      *
  594.      *        Public Library Function
  595.      */
  596.  
  597. ULONG __asm __saveds muGetTaskOwner(register __d0 struct Task *task)
  598. {
  599.     if (!task)
  600.         task = SysBase->ThisTask;
  601.     return(GetTaskOwner(task));
  602. }
  603.  
  604.  
  605.     /*
  606.      *        Get the Owner (struct muExtOwner *) of a Task
  607.      *
  608.      *        Public Library Function
  609.      */
  610.  
  611. struct muExtOwner __asm __saveds *muGetTaskExtOwner(register __d0 struct Task *task)
  612. {
  613.     if (!task)
  614.         task = SysBase->ThisTask;
  615.     return(GetTaskExtOwner(task));
  616. }
  617.  
  618.  
  619.     /*
  620.      *        Free an Extended Owner structure
  621.      *
  622.      *        Public Library Function
  623.      */
  624.  
  625. void __asm __saveds muFreeExtOwner(register __a0 struct muExtOwner *owner)
  626. {
  627.     ULONG size;
  628.  
  629.     if (owner) {
  630.         size = sizeof(struct muExtOwner)+owner->NumSecGroups*sizeof(UWORD);
  631.         Free(owner, size);
  632.     }
  633. }
  634.  
  635.  
  636.     /*
  637.      *        Kill a task or process
  638.      *
  639.      *        Public Library Function
  640.      *
  641.      *        This function may be called by root only!
  642.      */
  643.  
  644. BOOL __asm __saveds muKill(register __d0 struct Task *task)
  645. {
  646.     BOOL res = FALSE;
  647.     UBYTE *sp;
  648.     ULONG size;
  649.     struct muExtOwner *xowner;
  650.  
  651.     xowner = GetTaskExtOwner(SysBase->ThisTask);
  652.     if (task && (task != SysBase->ThisTask) && (task != muBase->Server) &&
  653.          (muGetRelationshipA(xowner, NULL, NULL) & muRelF_ROOT_UID)) {
  654.         Disable();
  655.         switch (task->tc_Node.ln_Type) {
  656.             case NT_TASK:
  657.                 RemTask(task);
  658.                 res = TRUE;
  659.                 break;
  660.  
  661.             case NT_PROCESS:
  662.                 Remove(task);
  663.                 task->tc_State = TS_READY;
  664.                 sp = task->tc_SPReg;
  665.                 if (SysBase->AttnFlags & AFF_68881) {
  666.                     if (size = *(ULONG *)sp) {
  667.                         sp += 110;
  668.                         if (size == 0x90)
  669.                             sp += 12;
  670.                         if ((SysBase->LibNode.lib_Version > 37) || ((SysBase->LibNode.lib_Version == 37) &&
  671.                                                                                   (SysBase->LibNode.lib_Revision >= 132)))
  672.                             sp += 2;
  673.                         size = sp[1];
  674.                         sp += size;
  675.                     }
  676.                     sp += 4;
  677.                 }
  678.                 *(ULONG *)sp = (ULONG)CleanUpBody;
  679.                 AddHead(&SysBase->TaskReady, task);
  680.                 res = TRUE;
  681.                 break;
  682.         }
  683.         Enable();
  684.     }
  685.     muFreeExtOwner(xowner);
  686.     return(res);
  687. }
  688.  
  689.  
  690.     /*
  691.      *        Clean up a dead process
  692.      */
  693.  
  694. static void __saveds CleanUpBody(void)
  695. {
  696.     struct Task *task;
  697.     struct Screen *scr, *t;
  698.     struct Window *win;
  699.     struct MsgPort *port;
  700.     struct Requester *req;
  701.     BOOL doclose;
  702.  
  703.     task = SysBase->ThisTask;
  704.     Forbid();
  705.     scr = IntuitionBase->FirstScreen;
  706.     while (scr) {
  707.         doclose = FALSE;
  708.         win = scr->FirstWindow;
  709.         while (win)
  710.             if ((port = win->UserPort) && (port->mp_SigTask == task)) {
  711.                 ModifyIDCMP(win, NULL);
  712.                 ClearDMRequest(win);
  713.                 ClearMenuStrip(win);
  714.                 ClearPointer(win);
  715.                 while (req = win->FirstRequest)
  716.                     EndRequest(req, win);
  717.                 CloseWindow(win);
  718.                 doclose = TRUE;
  719.                 win = scr->FirstWindow;
  720.             } else
  721.                 win = win->NextWindow;
  722.         t = scr->NextScreen;
  723.         if (doclose && ((scr->Flags & SCREENTYPE) != WBENCHSCREEN))
  724.             CloseScreen(scr);
  725.         scr = t;
  726.     }
  727.     Exit(NULL);
  728. }
  729.  
  730.  
  731.     /*
  732.      *        Freeze a task or process
  733.      *
  734.      *        Public Library Function
  735.      *
  736.      *        This function may be called by root only!
  737.      */
  738.  
  739. BOOL __asm __saveds muFreeze(register __d0 struct Task *task)
  740. {
  741.     BOOL res = FALSE;
  742.     struct muExtOwner *xowner;
  743.  
  744.     xowner = GetTaskExtOwner(SysBase->ThisTask);
  745.     if (task && (task != SysBase->ThisTask) && (task != muBase->Server) &&
  746.          (muGetRelationshipA(xowner, NULL, NULL) & muRelF_ROOT_UID)) {
  747.         Disable();
  748.         switch (task->tc_Node.ln_Type) {
  749.             case NT_TASK:
  750.             case NT_PROCESS:
  751.                 if (task->tc_State < 7) {
  752.                     Remove(task);
  753.                     AddHead((struct List *)&muBase->Frozen, task);
  754.                     task->tc_State += 7;
  755.                     res = TRUE;
  756.                 }
  757.                 break;
  758.         }
  759.         Enable();
  760.     }
  761.     muFreeExtOwner(xowner);
  762.     return(res);
  763. }
  764.  
  765.  
  766.     /*
  767.      *        Unfreeze a task or process
  768.      *
  769.      *        Public Library Function
  770.      *
  771.      *        This function may be called by root only!
  772.      */
  773.  
  774. BOOL __asm __saveds muUnfreeze(register __d0 struct Task *task)
  775. {
  776.     BOOL res = FALSE;
  777.     struct muExtOwner *xowner;
  778.  
  779.     xowner = GetTaskExtOwner(SysBase->ThisTask);
  780.     if (task && (muGetRelationshipA(xowner, NULL, NULL) & muRelF_ROOT_UID)) {
  781.         Disable();
  782.         switch (task->tc_Node.ln_Type) {
  783.             case NT_TASK:
  784.             case NT_PROCESS:
  785.                 if (task->tc_State >= 7) {
  786.                     Remove(task);
  787.                     if ((task->tc_State -= 7) == TS_READY)
  788.                         Enqueue(&SysBase->TaskReady, task);
  789.                     else
  790.                         Enqueue(&SysBase->TaskWait, task);
  791.                     res = TRUE;
  792.                 }
  793.                 break;
  794.         }
  795.         Enable();
  796.     }
  797.     muFreeExtOwner(xowner);
  798.     return(res);
  799. }
  800.